home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS18.ADF
/
Progs
/
StarProbe
/
SPEVAL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-27
|
12KB
|
495 lines
/****************************************************************************
*** ***
*** S T A R P R O B E E V A L U A T E ***
*** ***
****************************************************************************/
/*****
*** This module evaluates all physical parameters at the current mass
*** position. All physics/calculus emanates from here.
*****/
#include "stdio.h"
#include "math.h"
#include "limits.h"
#include "spmac.h"
#include "spref.h"
int ixstop,ixstart;
double m2,init_p,init_t,init_l,init_r,massaccum;
/*****
*** M e a n M o l e c u l a r W e i g h t
*****/
double meanmolweight(h_frac,he_frac,m_frac)
double h_frac, /* fraction of hydrogen */
he_frac, /* fraction of helium */
m_frac; /* fraction of metals */
{ /* h+he+m frac must = 1.0 */
iam(80);
static double val;
block(in,"meanmolweight",(h_frac+he_frac+m_frac));
assert0((h_frac+he_frac+m_frac),==,1.0);
val = (1.0/((2*h_frac)+(0.75*he_frac)+(0.5*m_frac)));
block(out,"meanmolweight",val);
return(val);
}
/*****
*** E v a l D e n s i t y
***
*** Ref: Motz 12.11, pg. 282
*****/
double eval_density(p,t)
double p,t;
{
iam(81);
static double val;
static double mpk = MP/K;
block(in,"eval_density",p);
assert1(t,>,0.0);
val = u*mpk*p / t;
assert1(val,<,500.0);
block(out,"eval_density",val);
return(val);
}
/*****
*** E v a l E n e r g y R a t e
***
*** Ref: Motz pp. 344-346 (13.58)
*****/
double eval_energy_rate(d,t)
double d,t;
{
iam(41);
double val,t6,e_pp,e_cn,p,it;
int pp_ix, cn_ix;
block(in,"eval-energy",t);
it = pow((1.0e6/t),0.33333);
e_pp = 2.36e6 *d*X*X*it*it*exp(-33.8*it);
e_cn = 0.786e28 *d*X*Z*it*it*exp(-152.3*it)*exp(7.25/t);
val = e_pp + e_cn;
block(mid,"eval-energy e_pp",e_pp);
block(mid,"eval-energy e_cn",e_cn);
block(out,"eval-energy",val);
return(val);
}
/*****
*** E v a l O p a c i t y
***
*** Ref: Motz pp. 165-166
*****/
double eval_opacity(p,t)
double p,t;
{
iam(31);
static double val,e1,e2,d1,d2,t2,t3,t4,d,t6,d3,d4,d5;
block(in,"eval-opacity",0.0);
t6 = t * 1.0e-6;
d = eval_density(p,t);
t2 = t6*t6; t3 = t2*t6; t4 = t3*t6;
d1 = 6.5e4 * Z * (1.0-(0.05*t6))/(t2+(2.5*t4));
d1*= exp(-7.75*d*(1.0+X)/t3);
d2 = -abs((0.667-2.873*t6));
d2 = 1.0 + 5.5*exp(d2);
d3 = X/((250.0*t4)-t2);
d4 = Y/(250.0*t4);
d5 = 4.15e4 * (d3 + (d4*d2));
e1 = d1 + (d5 * exp(-2.0*d*(1.0+X)/t3));
e2 = (225.0-(115.0*X)-(190.0*Y))/pow(t6,3.5);
if (t6<10.0){
val = (0.19*(1.0+X))+(e1*d*(1.0+X));
val *= 0.715;
}
else if (t6<=20.0){
val = (0.19*(1.0+X))+(e1*d*(1.0+X))+
(d*(1.0-0.1*t6)*((1.0+X)*e1-e2));
val *= 0.9;
}
else
val = (0.19*(1.0+X))+e2*d;
assert1(val,>,0.0);
block(out,"eval-opacity",val);
return(val);
}
/*****
*** R a d i a t i v e
***
*** Ref: Motz pg. 311
*****/
int radiative(m,p,t,l,r)
double m,p,t,l,r;
{
iam(82);
int val;
block(in,"radiative",t);
assert2(p,>,0.0);
assert2(l,>,0.0);
assert2(m,>,0.0);
if (pow(t,5.0)/(eval_opacity(p,t)*p*l/m) <= 1.0e10)
val = 0;
else
val = 1;
block(out,"radiative",(double)val);
return(val);
}
/*****
*** P r e s s u r e F u n c t i o n
***
*** Ref: Motz pg. 292 or Clayton Eq 6-14
*****/
double press_func(m,p,t,l,r)
double m,p,t,l,r;
{
iam(20);
static double val;
block(in,"press-func",m);
assert2(r,>,0.0);
val=((-G*m)/(4.0*PI*r*r*r*r));
block(out,"press-func",val);
return(val);
}
/*****
*** T e m p e r a t u r e F u n c t i o n
***
*** Ref: Clayton pg. 443, Motz pp. 252-253
*****/
double temp_func(m,p,t,l,r)
double m,p,t,l,r;
{
iam(30);
double tau2, val, opcty;
block(in,"temp-func",t);
if (radiative(m,p,t,l,r)){
opcty = eval_opacity(p,t);
assert2(t,>,0.0);
assert2(r,>,10000.0);
val = ((-3.0*opcty*l)/
(4.0*A*C*t*t*t*16.0*PI_SQ*r*r*r*r));
}
else{
tau2 = 1.0 + ((4.0-3.0*B)*(poly-1.0))/(B*B+3.0*(poly-1.0)*(1.0-B)*(4.0+B));
block(mid,"temp-func tau2",tau2);
val = ((tau2-1.0)*t/(tau2*p)) * press_func(m,p,t,l,r);;
}
block(out,"temp-func",val);
return(val);
}
/*****
*** L u m i n o s i t y F u n c t i o n
***
*** Ref: Motz pg. 292
*****/
double lum_func(m,p,t,l,r)
double m,p,t,l,r;
{
iam(40);
static double val,d;
block(in,"lum-func",l);
d = eval_density(p,t);
val = eval_energy_rate(d,t);
assert2(val,>=,0.0);
block(out,"lum-func",val);
return(val);
}
/*****
*** R a d i u s F u n c t i o n
***
*** Ref: Clayton Eq 6-13
*****/
double radius_func(m,p,t,l,r)
double m,p,t,l,r;
{
iam(50);
static double val;
block(in,"radius-func",r);
assert2(r,>,0.0);
val = 1.0/(4.0*PI*r*r*eval_density(p,t));
block(out,"radius-func",val);
return(val);
}
/*****
*** F u n c
***
*** Calls the correct differential function for the integrator.
*****/
double func(i,m,p,t,l,r)
int i;
double m,p,t,l,r;
{
iam(13);
static double val;
block(in,"func",(double)i);
block(mid,"func m",m);
block(mid,"func p",p);
block(mid,"func t",t);
block(mid,"func l",l);
block(mid,"func r",r);
switch (i){
case 0: val = press_func(m,p,t,l,r);
break;
case 1: val = temp_func(m,p,t,l,r);
break;
case 2: val = lum_func(m,p,t,l,r);
break;
case 3: val = radius_func(m,p,t,l,r);
break;
default:assert_error(proc_num,(double)i,4.0,0.0,0.0,0.0,0.0,0.0);
}
block(out,"func",val);
return (val);
}
/*****
*** I n t e g r a t e
***
*** Solves for (P,T,L,R) using Runge_Kotta algorithm.
***
*** Ref: Clayton pp. 448-450
*****/
void integrate(ixstrt,ixstop,ixinc,p,t,l,r)
int ixstrt,ixstop,ixinc;/* array index control */
double p,t,l,r;
{
iam(12);
double k1[4], k2[4], k3[4], k4[4], h, h2, mh, mh2;
double delta_p,delta_t,delta_l,delta_r;
int i,f;
block(in,"integrate",0.0);
i = ixstrt;
while (1){
block(mid,"integrate ***************************",(double) i);
assert0(i,>=,0);
assert0(i,<,gradsteps);
massinc=massgrad[i]*ixinc*mass;
h = massinc; h2 = h/2.0;
mh = m + h; mh2 = m + h2;
block(mid,"integrate m",m);
block(mid,"integrate h",h);
block(mid,"integrate p",p);
block(mid,"integrate t",t);
block(mid,"integrate l",l);
block(mid,"integrate r",r);
block(mid,"integrate *** K1 ****",0.0);
for (f=0;f<4;f++)
k1[f] = func(f,m,p,t,l,r);
block(mid,"integrate *** K2 ****",0.0);
for (f=0;f<4;f++)
k2[f] = func(f,mh2,p+h2*k1[0],t+h2*k1[1],l+h2*k1[2],r+h2*k1[3]);
block(mid,"integrate *** K3 ****",0.0);
for (f=0;f<4;f++)
k3[f] = func(f,mh2,p+h2*k2[0],t+h2*k2[1],l+h2*k2[2],r+h2*k2[3]);
block(mid,"integrate *** K4 ****",0.0);
for (f=0;f<4;f++)
k4[f] = func(f,mh,p+h*k3[0],t+h*k3[1],l+h*k3[2],r+h*k3[3]);
delta_p=(h*(k1[0]+k2[0]+k2[0]+k3[0]+k3[0]+k4[0])/6.0);
delta_t=(h*(k1[1]+k2[1]+k2[1]+k3[1]+k3[1]+k4[1])/6.0);
delta_l=(h*(k1[2]+k2[2]+k2[2]+k3[2]+k3[2]+k4[2])/6.0);
delta_r=(h*(k1[3]+k2[3]+k2[3]+k3[3]+k3[3]+k4[3])/6.0);
p += delta_p;
t += delta_t;
l += delta_l;
r += delta_r;
pressure = p;
temp = t;
lum = l;
radius = r;
density = eval_density(p,t);
opacity = eval_opacity(p,t);
pressgrad[i] = p;
tempgrad[i] = t;
lumgrad[i] = l;
radiusgrad[i] = r;
densgrad[i] = density;
opctygrad[i] = (radiative(m,p,t,l,r)) ? opacity : 0.0;
m+=massinc;
tmassgrad[i] = m;
energygrad[i] = eval_energy_rate(density,t);
block(mid,"integrate delta_p=",delta_p);
block(mid,"integrate delta_t=",delta_t);
block(mid,"integrate delta_l=",delta_l);
block(mid,"integrate delta_r=",delta_r);
if (debug > 0) report_detail();
if (i==ixstop) break;
i += ixinc;
}
results[0] [rix] = p;
results[1] [rix] = t;
results[2] [rix] = l;
results[3] [rix] = r;
block(mid,"integrate ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !",0.0);
block(out,"integrate",0.0);
}
/*****
*** C a l l I n t e g r a t o r
***
*** Sets up the global variables and parameters for the Integrate func.
*****/
void call_integrator(dir,ix,p_mult,t_mult,l_mult,r_mult)
int dir,ix;
double p_mult,t_mult,l_mult,r_mult;
{
iam(14);
block(in,"call-integrator",dir);
block(mid,"call-integrator",ix);
if (dir==in) { /* inward from surface to fitting point */
ixstart = gradsteps - 1;
/*init_p = 0.667*G*SM/(SR*SR*radratio*radratio*10.0);*/
init_p = effpress * p_mult;
init_t = efftemp * t_mult;
init_r = SR*radratio * r_mult;
/*init_l = 4.0*PI*init_r*init_r*SB*pow(efftemp,4.0);*/
init_l = SL*lumratio * l_mult;
rix=ix;m=mass;
pressure=init_p;temp=init_t;lum=init_l;radius=init_r;
density=eval_density(init_p,init_t);opacity=eval_opacity(init_p,init_t);
if (trace_me) report_detail();
integrate(ixstart,ixstop+1,-1,init_p,init_t,init_l,init_r);
}
else { /*outward from center to fitting point */
init_p = corepress * p_mult;
init_t = coretemp * t_mult;
init_l = l_mult * SL * lumratio / 1.0e8;
init_r = r_mult * pow((3.0*mass*massgrad[0]/(4.0*PI*coredensity)),0.33333);
rix=ix;m=mass*massgrad[0];
pressure=init_p;temp=init_t;lum=init_l;radius=init_r;
density=eval_density(init_p,init_t);opacity=eval_opacity(init_p,init_t);
pressgrad[0] = init_p;
tempgrad[0] = init_t;
lumgrad[0] = init_l;
radiusgrad[0] = init_r;
densgrad[0] = density;
opctygrad[0] = (radiative(m,init_p,init_t,init_l,init_r)) ? opacity : 0.0;
tmassgrad[0] = m;
energygrad[0] = eval_energy_rate(density,init_t);
if (trace_me) report_detail();
integrate(1,ixstop,1,init_p,init_t,init_l,init_r);
}
block(out,"call-integrator",0.0);
}
/*****
*** E v a l u a t e
***
*** Calls Integrate 6 times for each trial integration:
*** 3 from the center, 3 from the surface; each ending when
*** m=mass/2. The results are then massaged to get new starting
*** values for the next trial. The trials stop when the results
*** become consistent.
***
*** The initial values come from Set_Boundary_Values.
*****/
void evaluate()
{
iam(10);
int tries;
block(in,"evaluate",0.0);
massaccum=0.0;
m2=mass*fitptmass;
ixstop=-1;
do { /* find mass midpoint */
ixstop++;
massaccum+=massgrad[ixstop]*mass;
} while (massaccum<m2);
assert0(massaccum,>,0.0);
assert0(massaccum,<=,mass);
block(mid,"evaluate ixstop=",(double) ixstop);
tries = 0;
for (;;) {
tries++;
report_global();
printf("Starting trial integration #%d\n",tries);
call_integrator(out,0,1.0, 1.0, 1.0, 1.0 );
call_integrator(in, 1,1.0, 1.0, 1.0, 1.0 );
dump_data(tries);
if (!discontinuity()) break;
if (tries >= max_tries) break;
if (!closer_fit(ixstop)){
printf("... integrating with variances ...\n");
call_integrator(out,2,adj_p,1.0, 1.0, 1.0 );
call_integrator(out,3,1.0, adj_t,1.0, 1.0 );
call_integrator(in, 4,1.0, 1.0, adj_l,1.0 );
call_integrator(in, 5,1.0, 1.0, 1.0, adj_r);
}
report_results();
new_boundary_conditions();
}
block(out,"evaluate",0.0);
}